<?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of BWTimeSlotType
 *
 * @author jianfeng
 */
class BWTimeSlotType extends BWKeyValueType {

    //put your code here
    public $activeTime;
    public $expireTime;
    public $repeatType;
    public $bookingStartTimeOffset;
    public $bookingStartTimeOffsetUnit;
    public $bookingEndTimeOffset;
    public $bookingEndTimeOffsetUnit;
    public $bookingCancelTimeOffset;
    public $bookingCancelTimeOffsetUnit;
    public $timeSlotConfigList = array();
    protected $isInputableListLoaded = false;

    public function getInputableList($nameList = false, $data = NULL) {
        //parent::getInputableList($nameList, $data);
        $timeOfNow = time();
        $expireTime = $this->getExpireTime();
        if ($expireTime < time()) {
            return array();
        }

        //each time, when get inputable list, will load config and 
        //undate new inputable
        if (!$this->isInputableListLoaded) {

            $startTimeStamp = NULL;
            $endTimeStamp = null;
            $bookingStartTimeStamp = null;
            $bookingEndTimeStamp = null;
            $bookingCancelTimeStamp = null;
            $repeatType = NULL;
            $splitTimes = NULL;
            $timeSplit = NULL;

            $congfigList = $this->getTimeSlotConfigList();
            //each time will check config and update inputable list
            foreach ($congfigList as $config) {
                if (isset($config['startTime'])) {
                    $startTime = new DateTime();
                    //$startTimeStamp = $startTime->getTimestamp();
                    $configStartTimeStamp = $config['startTime'];
                    //if ($startTimeStamp < $configStartTimeStamp) {
                    $startTime->setTimestamp($configStartTimeStamp);
                    //}
                    $startTimeStamp = $startTime->getTimestamp();
                }

                $splitTimes = 1;
                if (isset($config['splitTimes'])) {
                    $splitTimes = $config['splitTimes'];
                }

                if (isset($config['length']) && isset($config['lengthUnit'])) {
                    $length = $config['length'];
                    $lengthUnit = $config['lengthUnit'];

                    $interval = $length;

                    if ($splitTimes != NULL) {
                        $interval = $length / $splitTimes;
                    }

                    if ($interval > 1)
                        $lengthUnit .= 's';

                    $endTime = new DateTime();
                    $endTime->setTimestamp($startTimeStamp);
                    date_add($endTime, date_interval_create_from_date_string($interval . ' ' . $lengthUnit));
                    $endTimeStamp = $endTime->getTimestamp();
                }

                $timeSplit = $endTimeStamp - $startTimeStamp;

                $description = $config['timeSlotDescription'];

                $bookingStartOffset = $this->getBookingStartTimeOffset();
                $bookingStartOffsetUnit = $this->getBookingStartTimeOffsetUnit();
                $bookingEndOffset = $this->getBookingEndTimeOffset();
                $bookingEndOffsetUnit = $this->getBookingEndTimeOffsetUnit();
                $bookingCancelOffset = $this->getBookingCancelTimeOffset();
                $bookingCancelOffsetUnit = $this->getBookingCancelTimeOffsetUnit();

                $bookingStartTime = new DateTime();
                $bookingStartTime->setTimestamp($startTimeStamp);
                if ($bookingStartOffset != NULL && $bookingStartOffsetUnit != NULL) {
                    $offsetUnit = $bookingStartOffsetUnit;
                    if ($bookingStartOffset > 1)
                        $offsetUnit = $bookingStartOffsetUnit . 's';
                    date_sub($bookingStartTime, date_interval_create_from_date_string($bookingStartOffset . ' ' . $offsetUnit));
                    $bookingStartTimeStamp = $bookingStartTime->getTimestamp();
                }

                $bookingEndTime = new DateTime();
                $bookingEndTime->setTimestamp($endTimeStamp);
                if ($bookingEndOffset != NULL && $bookingEndOffsetUnit != NULL) {
                    $offSetUnit = $bookingEndOffsetUnit;
                    if ($bookingEndOffset > 1)
                        $offSetUnit = $bookingEndOffsetUnit . 's';
                    $bookingEndTime = date_sub($bookingEndTime, date_interval_create_from_date_string($bookingEndOffset . ' ' . $offSetUnit));
                    $bookingEndTimeStamp = $bookingEndTime->getTimestamp();
                }

                $bookingCancelTime = new DateTime();
                $bookingCancelTime->setTimestamp($startTimeStamp);
                if ($bookingCancelOffset != NULL && $bookingCancelOffsetUnit != NULL) {
                    $offSetUnit = $bookingCancelOffsetUnit;
                    if ($bookingCancelOffset > 1)
                        $offSetUnit = $bookingCancelOffsetUnit . 's';
                    $bookingCancelTime = date_sub($bookingCancelTime, date_interval_create_from_date_string($bookingCancelOffset . ' ' . $offSetUnit));
                    $bookingCancelTimeStamp = $bookingCancelTime->getTimestamp();
                }

                $this->addTimeSlotByInterval($startTimeStamp, $endTimeStamp, $bookingStartTimeStamp, $bookingEndTimeStamp, $bookingCancelTimeStamp, $timeSplit, $description, $splitTimes);

                if (isset($config['repeatType'])) {
                    $repeatType = $config['repeatType'];
                }

                //populate bookable time from now
                $todayDateTime = Date('Y-m-d');
                $startTimeWithTime = date('H:i:s', $startTimeStamp);
                $today10am = $todayDateTime . ' 10:00:00';

                $repeatStartTime = new DateTime($todayDateTime . ' ' . $startTimeWithTime);
                date_sub($repeatStartTime, date_interval_create_from_date_string('3 days'));
                $repeatStartTimeStamp = $repeatStartTime->getTimestamp();

                $repeatEndTime = new DateTime();
                $repeatEndTime->setTimestamp($repeatStartTimeStamp);
                date_add($repeatEndTime, date_interval_create_from_date_string($interval . ' ' . $lengthUnit));
                $repeatEndTimeStamp = $repeatEndTime->getTimestamp();

                $repeatBookingStartTime = new DateTime();
                $repeatBookingStartTime->setTimestamp($repeatStartTimeStamp);
                $repeatBookingStartTimeStamp = NULL;
                if ($bookingStartOffset != NULL && $bookingStartOffsetUnit != NULL) {
                    $offSetUnit = $bookingStartOffsetUnit;
                    if ($bookingStartOffset > 1)
                        $offSetUnit = $bookingStartOffsetUnit . 's';
                    date_sub($repeatBookingStartTime, date_interval_create_from_date_string($bookingStartOffset . ' ' . $offSetUnit));
                    $repeatBookingStartTimeStamp = $repeatBookingStartTime->getTimestamp();
                }

                $repeatBookingEndTimeStamp = NULL;
                $repeatBookingEndTime = new DateTime();
                $repeatBookingEndTime->setTimestamp($repeatEndTimeStamp);
                if ($bookingEndOffset != NULL && $bookingEndOffsetUnit != NULL) {
                    $offSetUnit = $bookingEndOffsetUnit;
                    if ($bookingEndOffset > 1)
                        $offSetUnit = $bookingEndOffsetUnit . 's';
                    $repeatBookingEndTime = date_sub($repeatBookingEndTime, date_interval_create_from_date_string($bookingEndOffset . ' ' . $offSetUnit));
                    $repeatBookingEndTimeStamp = $repeatBookingEndTime->getTimestamp();
                }

                $repeatBookingCancelTimeStamp = NULL;
                $repeatBookingCancelTime = new DateTime();
                $repeatBookingCancelTime->setTimestamp($repeatStartTimeStamp);
                if ($bookingCancelOffset != NULL && $bookingCancelOffsetUnit != NULL) {
                    $offSetUnit = $bookingCancelOffsetUnit;
                    if ($bookingCancelOffset > 1)
                        $offSetUnit = $bookingCancelOffsetUnit . 's';
                    $repeatBookingCancelTime = date_sub($repeatBookingCancelTime, date_interval_create_from_date_string($bookingCancelOffset . ' ' . $offSetUnit));
                    $repeatBookingCancelTimeStamp = $repeatBookingCancelTime->getTimestamp();
                }

                if ($repeatType == 'repeatEveryDay') {
                    for ($i = 0; $i < 100; $i++) {
                        date_add($repeatStartTime, date_interval_create_from_date_string('1 day'));
                        $repeatStartTimeStamp = $repeatStartTime->getTimestamp();
                        date_add($repeatEndTime, date_interval_create_from_date_string('1 day'));
                        $repeatEndTimeStamp = $repeatEndTime->getTimestamp();
                        date_add($repeatBookingStartTime, date_interval_create_from_date_string('1 day'));
                        $repeatBookingStartTimeStamp = $repeatBookingStartTime->getTimestamp();
                        date_add($repeatBookingEndTime, date_interval_create_from_date_string('1 day'));
                        $repeatBookingEndTimeStamp = $repeatBookingEndTime->getTimestamp();
                        date_add($repeatBookingCancelTime, date_interval_create_from_date_string('1 day'));
                        $repeatBookingCancelTimeStamp = $repeatBookingCancelTime->getTimestamp();
                        $todayDateTime = Date('Y-m-d');
                        $today10am = $todayDateTime . ' 10:00:00';
                        $realAllowBookingTime = new DateTime($today10am);
                        $today10amStamp = $realAllowBookingTime->getTimestamp();
                        //date_add($realAllowBookingTime, date_interval_create_from_date_string('1 day'));
                        //$realAllowBookingTimeStamp = $realAllowBookingTime->getTimestamp();

                        if ($repeatBookingStartTimeStamp > $today10amStamp)
                            break;

                        if ($repeatEndTimeStamp > $this->expireTime)
                            break;

                        //$realAllowBookingTime = $today10am + $bookingStartTimeOffset;
                        //if ($repeatBookingStartTimeStamp < $today10amStamp && $today10amStamp < $repeatBookingEndTimeStamp) {
                        $this->addTimeSlotByInterval($repeatStartTimeStamp, $repeatEndTimeStamp, $repeatBookingStartTimeStamp, $repeatBookingEndTimeStamp, $repeatBookingCancelTimeStamp, $timeSplit, $description, $splitTimes);
                        //}
                    }
                }
            }

            //get inputbale list
            //$inputableList = $this->getAttributeNode()->getChildren();
            $parentId = $this->getAttributeNode()->getId();
            $current = time();
            $sql = "select t1._id, t1.name,t1.value from tbl_input_attribute t1, tbl_input_attribute t2, tbl_input_attribute t3 where "
                    . "t1._id = t2.parent_id and t2.name = 'endTime' and t2.value > " . $current . " and t1._id = t3.parent_id and t3.name = 'bookingEndTime' "
                    . " and t3.value >" . $current . " and t1.parent_id = " . $parentId;
            $view = $this->getAttributeNode()->getRepository()->getView(array('sql' => $sql));
            foreach ($view->rows as $id => $row) {
                $attr = new BWInputAttribute($id);
                $timeSlot = new BWBookingTimeSlot();
                $timeSlot->id = $id;
                $timeSlot->timeSlotId = $attr->name;
                $timeSlot->description = $attr->value;
                $timeSlot->startTime = $attr->getAttribute('startTime')->getValue();
                $timeSlot->endTime = $attr->getAttribute('endTime')->getValue();
                $timeSlot->bookingStartTime = $attr->getAttribute('bookingStartTime')->getValue();
                $timeSlot->bookingEndTime = $attr->getAttribute('bookingEndTime')->getValue();
                $timeSlot->bookingCancelTime = $attr->getAttribute('bookingCancelTime')->getValue();
                $this->inputableList[$id] = $timeSlot;
            }
            /*
              foreach ($inputableList as $id => $attr) {
              $timeSlot = new BWBookingTimeSlot();
              $timeSlot->id = $id;
              $timeSlot->timeSlotId = $attr->name;
              $timeSlot->description = $attr->value;
              $timeSlot->startTime = $attr->getAttribute('startTime')->getValue();
              $timeSlot->endTime = $attr->getAttribute('endTime')->getValue();
              $timeSlot->bookingStartTime = $attr->getAttribute('bookingStartTime')->getValue();
              $timeSlot->bookingEndTime = $attr->getAttribute('bookingEndTime')->getValue();
              $this->inputableList[$id] = $timeSlot;
              }
             * 
             */
            $this->isInputableListLoaded = TRUE;
            return $this->inputableList;
        }
    }

    protected function addTimeSlotByInterval($startTimeStamp, $endTimeStamp, $bookingStartTimeStamp, $bookingEndTimeStamp, $bookingCancelTimeStamp, $interval, $description = NULL, $repeatTime = NULL) {
        $todayDate = Date('Y-m-d');
        $today10am = $todayDate . ' 10:00:00';
        $todayDateTime = new DateTime($today10am);
        $today10amStamp = $todayDateTime->getTimestamp();
        $activeTimeStamp = $this->getActiveTime();
        $activeTime = date('Y-m-d H:i:s', $activeTimeStamp);
        if (is_numeric($repeatTime) && $repeatTime > 0) {
            //$timeSplit = ($repeatEndTimeStamp - $repeatStartTimeStamp) / $splitTimes;           
            for ($i = 0; $i < $repeatTime; $i++) {
                $splitStartTimeStamp = $startTimeStamp + $interval * $i;
                $splitEndTimeStamp = $endTimeStamp + $interval * $i;
                $splitBookingStartTimeStamp = $bookingStartTimeStamp + $interval * $i;
                $splitBookingEndTimeStamp = $bookingEndTimeStamp + $interval * $i;
                $splitBookingCancelTimeStamp = $bookingCancelTimeStamp + $interval * $i;

                //if ($splitBookingStartTimeStamp < $today10amStamp && $today10amStamp < $splitBookingEndTimeStamp && $splitEndTimeStamp > time()) {
                if ($splitEndTimeStamp > time() && $splitStartTimeStamp >= $activeTimeStamp) {
                    //if (time() <= $splitBookingEndTimeStamp) {
                    if (!$this->getTimeSlotInputbale($splitStartTimeStamp, $splitEndTimeStamp, $splitBookingStartTimeStamp, $splitBookingEndTimeStamp, $description)) {
                        $this->addTimeSlotInputable($splitStartTimeStamp, $splitEndTimeStamp, $splitBookingStartTimeStamp, $splitBookingEndTimeStamp, $splitBookingCancelTimeStamp, $description);
                    }
                    //}
                }
            }
        }
    }

    protected function addTimeSlotInputable($startTime, $endTime, $bookingStartTime, $bookingEndTime, $bookingCancelTime, $description) {
        $timeSlotNode = new BWAttribute();
        $timeSlotNode->name = 'ts_' . $startTime . '_' . $endTime . '_' . $bookingStartTime . '_' . $bookingEndTime;
        $timeSlotNode->name = md5($timeSlotNode->name);
        $timeSlotNode->value = $description;
        $timeSlot = $this->getAttributeNode()->addChild($timeSlotNode);
        $timeSlot->addAttribute('startTime', $startTime);
        $timeSlot->addAttribute('endTime', $endTime);
        $timeSlot->addAttribute('description', $description);
        $timeSlot->addAttribute('bookingStartTime', $bookingStartTime);
        $timeSlot->addAttribute('bookingEndTime', $bookingEndTime);
        $timeSlot->addAttribute('bookingCancelTime', $bookingCancelTime);
    }

    protected function getTimeSlotInputbale($startTime, $endTime, $bookingStartTime, $bookingEndTime, $description = NULL) {
        $name = 'ts_' . $startTime . '_' . $endTime . '_' . $bookingStartTime . '_' . $bookingEndTime;
        $mdzName = md5($name);
        return $this->getAttributeNode()->getChild($mdzName);
    }

    //this function get active timeslot config list
    public function getTimeSlotConfigList($data = NULL) {
        if ($this->expireTime < time())
            return array();

        if ($this->timeSlotConfigList == NULL || empty($this->timeSlotConfigList)) {
            $messageList = $this->inputMedia->getMessageManager()->getMessageList();
            foreach ($messageList as $message) {
                //$timeSlotDescription = $message->description;
                $timeSlotDescription = $message->getMediaManager()->getMedia('description')->getContent();
                $startTime = $message->getMediaManager()->getMedia('startTime')->getContent();
                $startTime = strtotime($startTime);
                $length = $message->getMediaManager()->getMedia('length')->getContent();
                $lengthUnit = $message->getMediaManager()->getMedia('lengthUnit')->getContent();
                $splitTimes = $message->getMediaManager()->getMedia('splitTimes')->getContent();
                $repeatType = $message->getMediaManager()->getMedia('repeatType')->getContent();
                if ($startTime <= $this->getExpireTime()) {
                    $config = array();
                    $config['startTime'] = $startTime;
                    $config['length'] = $length;
                    $config['lengthUnit'] = $lengthUnit;
                    $config['timeSlotDescription'] = $timeSlotDescription;
                    $config['splitTimes'] = $splitTimes;
                    $config['repeatType'] = $repeatType;
                    array_push($this->timeSlotConfigList, $config);
                }
            }
            return $this->timeSlotConfigList;
        }
    }

    public function getRepeatType($data = NULL) {
        if ($this->repeatType == NULL) {
            $this->repeatType == $this->getMediaManager()->getMedia('repeatType');
        }
        return $this->repeatType;
    }

    /**
     * return timestamp for active time
     * @param type timeStamp
     */
    public function getActiveTime($data = NULL) {
        if ($this->activeTime == NULL) {
            $activeTimeMedia = $this->getMediaManager()->getMedia('activeTime');
            if ($activeTimeMedia instanceof BWMedia) {
                $activeTime = $activeTimeMedia->getContent();
                if (!is_numeric($activeTime)) {
                    $activeTimeStamp = strtotime($activeTime);
                    //$activeTimeMedia->content = $activeTimeStamp;
                    //$activeTimeMedia->save();
                    $this->activeTime = $activeTimeStamp;
                }
            }
        }
        return $this->activeTime;
    }

    /**
     * return timestamp for expire time
     * @param type $data
     */
    public function getExpireTime($data = NULL) {
        if ($this->expireTime == NULL) {
            $expireTimeMedia = $this->getMediaManager()->getMedia('expireTime');
            if ($expireTimeMedia instanceof BWMedia) {
                $expireTime = $expireTimeMedia->getContent();
                if (!is_numeric($expireTime)) {
                    $expireTimeStamp = strtotime($expireTime);
                    //$expireTimeMedia->content = $expireTimeStamp;
                    //$expireTimeMedia->save();
                    $this->expireTime = $expireTimeStamp;
                }
            }
        }
        return $this->expireTime;
    }

    public function getBookingStartTimeOffset($data = NULL) {
        if ($this->bookingStartTimeOffset == NULL) {
            $theMedia = $this->getMediaManager()->getMedia('bookingStartTimeOffset');
            if ($theMedia instanceof BWMedia) {
                $this->bookingStartTimeOffset = $theMedia->getContent();
            }
        }
        return $this->bookingStartTimeOffset;
    }

    public function getBookingStartTimeOffsetUnit($data = NULL) {
        if ($this->bookingStartTimeOffsetUnit == NULL) {
            $theMedia = $this->getMediaManager()->getMedia('bookingStartTimeOffsetUnit');
            if ($theMedia instanceof BWMedia) {
                $this->bookingStartTimeOffsetUnit = $theMedia->getContent();
            }
        }
        return $this->bookingStartTimeOffsetUnit;
    }

    public function getBookingEndTimeOffset($data = NULL) {
        if ($this->bookingEndTimeOffset == NULL) {
            $theMedia = $this->getMediaManager()->getMedia('bookingEndTimeOffset');
            if ($theMedia instanceof BWMedia) {
                $this->bookingEndTimeOffset = $theMedia->getContent();
            }
        }
        return $this->bookingEndTimeOffset;
    }

    public function getBookingEndTimeOffsetUnit($data = NULL) {
        if ($this->bookingEndTimeOffsetUnit == NULL) {
            $theMedia = $this->getMediaManager()->getMedia('bookingEndTimeOffsetUnit');
            if ($theMedia instanceof BWMedia) {
                $this->bookingEndTimeOffsetUnit = $theMedia->getContent();
            }
        }
        return $this->bookingEndTimeOffsetUnit;
    }

    public function getBookingCancelTimeOffset($data = NULL) {
        if ($this->bookingCancelTimeOffset == NULL) {
            $theMedia = $this->getMediaManager()->getMedia('bookingCancelTimeOffset');
            if ($theMedia instanceof BWMedia) {
                $this->bookingCancelTimeOffset = $theMedia->getContent();
            }
        }
        return $this->bookingCancelTimeOffset;
    }

    public function getBookingCancelTimeOffsetUnit($data = NULL) {
        if ($this->bookingCancelTimeOffsetUnit == NULL) {
            $theMedia = $this->getMediaManager()->getMedia('bookingCancelTimeOffsetUnit');
            if ($theMedia instanceof BWMedia) {
                $this->bookingCancelTimeOffsetUnit = $theMedia->getContent();
            }
        }
        return $this->bookingCancelTimeOffsetUnit;
    }

    public function addTimeSlotConfig($timeSlotConfig, $data = NULL) {
        if (is_array($timeSlotConfig) && $timeSlotConfig != NULL)
            array_push($this->timeSlotConfigList, $timeSlotConfig);
    }

    /*
      public function populateInputTypeByPostData($postData = NULL, $inputIndex = NULL) {
      self::populateInputTypeByPostData($postData, $inputIndex);
      //below convert time string to number of time
      $inputTypeMessageList = $this->getMessageManager()->getMessageList();
      foreach ($inputTypeMessageList as $name => $message) {
      $startTimeMedia = $message->getMedia('startTime');
      if ($startTimeMedia instanceof BWMedia) {
      $startTimeStamp = strtotime($startTimeMedia->getContent());
      //$startTimeMedia->content = $startTimeStamp;
      //$startTimeMedia->save();
      }
      }
      }
     * 
     */

    public static function getRepeatTypeList($data = NULL) {
        return array(
            'repeatEveryDay' => Yii::t('BWeSport', 'repeat every day'),
            'repeatInWeekDays' => Yii::t('BWeSport', 'repeat week days'),
            'repeatInSpecialDays' => Yii::t('BWeSport', 'repeat in special days'),
            'repeatEachWeek' => Yii::t('BWeSport', 'repeat each week'),
            'repeatEachMonth' => Yii::t('BWeSport', 'repeat each month')
        );
    }

    public static function getTimeUnitList($data = NULL) {
        return array(
            'minute' => Yii::t('BWeSport', 'minute'),
            'hour' => Yii::t('BWeSport', 'hour'),
            'day' => Yii::t('BWeSport', 'day'),
            'week' => Yii::t('BWeSport', 'week')
        );
    }

}
